/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.replica.replicaisland;

/**
 * A component that implements the "pop-out" AI behavior. Pop-out characters
 * alternate between hiding and appearing based on their distance from the
 * player. They do not move or normally attack.
 */
public class PopOutComponent extends GameComponent {
	private static final int DEFAULT_APPEAR_DISTANCE = 120;
	private static final int DEFAULT_HIDE_DISTANCE = 190;
	private static final int DEFAULT_ATTACK_DISTANCE = 0; // No attacking by
															// default.
	private float mAppearDistance;
	private float mHideDistance;
	private float mAttackDistance;
	private float mAttackDelay;
	private float mAttackLength;
	private float mAttackStartTime;
	private Vector2 mDistance;
	private int mState;
	private float mLastAttackCompletedTime;

	private final static int STATE_HIDDEN = 0;
	private final static int STATE_VISIBLE = 1;
	private final static int STATE_ATTACKING = 2;

	public PopOutComponent() {
		super();
		setPhase(ComponentPhases.THINK.ordinal());
		mDistance = new Vector2();
		reset();
	}

	@Override
	public void reset() {
		mAttackDelay = 0;
		mAttackLength = 0;
		mAttackDistance = DEFAULT_ATTACK_DISTANCE;
		mAppearDistance = DEFAULT_APPEAR_DISTANCE;
		mHideDistance = DEFAULT_HIDE_DISTANCE;
		mState = STATE_HIDDEN;
		mLastAttackCompletedTime = 0.0f;
	}

	@Override
	public void update(float timeDelta, BaseObject parent) {
		GameObject parentObject = (GameObject) parent;

		GameObjectManager manager = sSystemRegistry.gameObjectManager;
		if (manager != null) {
			GameObject player = manager.getPlayer();
			if (player != null) {
				mDistance.set(player.getPosition());
				mDistance.subtract(parentObject.getPosition());

				TimeSystem time = sSystemRegistry.timeSystem;
				final float currentTime = time.getGameTime();

				switch (mState) {
				case STATE_HIDDEN:
					parentObject.setCurrentAction(GameObject.ActionType.HIDE);
					if (mDistance.length2() < (mAppearDistance * mAppearDistance)) {
						mState = STATE_VISIBLE;
						mLastAttackCompletedTime = currentTime;
					}
					break;
				case STATE_VISIBLE:
					parentObject.setCurrentAction(GameObject.ActionType.IDLE);
					if (mDistance.length2() > (mHideDistance * mHideDistance)) {
						mState = STATE_HIDDEN;
					} else if (mDistance.length2() < (mAttackDistance * mAttackDistance)
							&& currentTime > mLastAttackCompletedTime
									+ mAttackDelay) {
						mAttackStartTime = currentTime;
						mState = STATE_ATTACKING;
					}
					break;
				case STATE_ATTACKING:
					parentObject.setCurrentAction(GameObject.ActionType.ATTACK);
					if (currentTime > mAttackStartTime + mAttackLength) {
						mState = STATE_VISIBLE;
						mLastAttackCompletedTime = currentTime;
					}
					break;
				default:
					assert false;
					break;
				}

			}
		}

	}

	public void setupAttack(float distance, float delay, float duration) {
		mAttackDistance = distance;
		mAttackDelay = delay;
		mAttackLength = duration;
	}

	public void setAppearDistance(float appearDistance) {
		mAppearDistance = appearDistance;
	}

	public void setHideDistance(float hideDistance) {
		mHideDistance = hideDistance;
	}

}
